﻿using System.ComponentModel;
using System.Linq;
using System.Windows;
using Fayshine.VA.Helpers;
using Fayshine.VA.RIAService.Web;
using Fayshine.VA.Controls;
using Fayshine.VA.Models;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System;
using System.Threading;
using System.Diagnostics;
using System.Text;

namespace Fayshine.VA.ViewModels
{

    public delegate void ResetHistoryChartEventHandler();
    public delegate void AppendHistoryPassengerFlowEventHandler(string title,bool isIn, List<HistoryPassengerFlow> firstHistoryPassengerFlow,List<HistoryPassengerFlow> secondHistoryPassengerFlow);
    public delegate void AppendMultiHistoryPassengerEventHandler(string title,bool isIn,params List<HistoryPassengerFlow>[] historyPassengerFlows);
    public delegate void AppendDayDurationHistoryPassengerEventHandler(string title, bool isIn, List<HistoryPassengerFlow> firstHistoryPassengerFlow, Dictionary<AreaExtend, List<HistoryPassengerFlow>> dtarea2HPFs); 

    public class SearchStatisticsViewModel : INotifyPropertyChanged
    {
        #region Private Fields

        private FayshineDomainContext m_Context = null;

        private string m_CurveTitle = string.Empty;
        public event ResetHistoryChartEventHandler ResetHisotryChartEvent;
        public event AppendHistoryPassengerFlowEventHandler AppendHistoryPassengerFlow;
        public event AppendDayDurationHistoryPassengerEventHandler AppendDayDurationHistoryPassenger;

        private List<AreaExtend> m_checkedAreas;

        private List<MonitorAreaGateExt> m_checkedGates;

        #endregion

        #region Properties

        public ObservableCollection<AreaExtend> AreaExtends
        {
            get;
            set;
        }

        public ObservableCollection<MonitorAreaGateExt> MonitorAreaGateExts
        {
            get;
            set;
        }

        public ObservableCollection<AreaExtend> AreaExtends2
        {
            get;
            set;
        }

        public ObservableCollection<MonitorAreaGateExt> MonitorAreaGateExts2
        {
            get;
            set;
        }

        public string CurveTitle
        {
            get
            {
                return m_CurveTitle;
            }
            set
            {
                m_CurveTitle = value;
                NofityPropertyChanged("CurveTitle");
            }
        }

        public List<passengerflowbymin> TempPassengerFlowbyMIn
        {
            set;
            get;
        }

        public List<AreaExtend> CheckedAreas
        {
            get { return m_checkedAreas; }
        }
        
        public List<MonitorAreaGateExt> CheckedGates
        {
            get { return m_checkedGates; }
        }

        #endregion

        public SearchStatisticsViewModel()
        {
            this.MonitorAreaGateExts = new ObservableCollection<MonitorAreaGateExt>();
            this.AreaExtends = new ObservableCollection<AreaExtend>();
            this.AreaExtends2 = new ObservableCollection<AreaExtend>();
            this.MonitorAreaGateExts2 = new ObservableCollection<MonitorAreaGateExt>();
            m_Context = new FayshineDomainContext();
        }

        #region Public Methods

        public void GetAllAreas()
        {
            var getAreasQuery = m_Context.GetAreasQuery();
            var loadShopsOperation = m_Context.Load(getAreasQuery, (s) =>
            {
                if (!s.HasError)
                {
                    AreaExtend tempAreaExt = null;
                    AreaExtend tempAreaExt2 = null;
                    s.Entities.ToList().ForEach(e =>
                    {
                        tempAreaExt = new AreaExtend();
                        tempAreaExt.ID = e.ID;
                        tempAreaExt.Name = e.Name;
                        tempAreaExt.Tag = e;
                        tempAreaExt.IsSelected = false;
                        this.AreaExtends.Add(tempAreaExt);

                        tempAreaExt2 = new AreaExtend();
                        tempAreaExt2.ID = e.ID;
                        tempAreaExt2.Name = e.Name;
                        tempAreaExt2.Tag = e;
                        tempAreaExt2.IsSelected = false;
                        this.AreaExtends2.Add(tempAreaExt2);
                    });
                }
                else
                {
                    MessageBox.Show(s.Error.Message + s.Error.StackTrace);
                }
                BusyIndicator indicator = Application.Current.RootVisual as BusyIndicator;
                indicator.IsBusy = false;
            }, true);
        }

        public void SelectAreasChanged(List<area> areas)
        {
            this.MonitorAreaGateExts.Clear();
            if (areas.Count > 0)
            {
                MonitorAreaGateExt tempMonitorExt;
                if (areas.Count == 1)
                {
                    MonitorAreaGateExt topMonitorExt = new MonitorAreaGateExt();
                    topMonitorExt.ID = areas[0].ID;
                    topMonitorExt.Name = "全部";
                    topMonitorExt.ParentID = areas[0].ParentID;
                    topMonitorExt.TypeID = 1;
                    topMonitorExt.IsSelected = true;
                    this.MonitorAreaGateExts.Add(topMonitorExt);

                    areas[0].gates.OrderBy(o => o.ID).each(e =>
                    {
                        tempMonitorExt = new MonitorAreaGateExt();
                        tempMonitorExt.ID = e.ID;
                        tempMonitorExt.ParentID = areas[0].ID;
                        tempMonitorExt.Name = e.Name;
                        tempMonitorExt.TypeID = 0;
                        tempMonitorExt.ParentMonitor = topMonitorExt;
                        tempMonitorExt.IsSelected = true;
                        topMonitorExt.Childs.Add(tempMonitorExt);
                        this.MonitorAreaGateExts.Add(tempMonitorExt);
                    });

                }
                else
                {
                    areas.each(a =>
                    {
                        tempMonitorExt = new MonitorAreaGateExt();
                        tempMonitorExt.ID = a.ID;
                        tempMonitorExt.Name = a.Name;
                        tempMonitorExt.ParentID = a.ParentID;
                        tempMonitorExt.TypeID = 1;
                        tempMonitorExt.IsSelected = true;
                        this.MonitorAreaGateExts.Add(tempMonitorExt);
                    });

                    tempMonitorExt = new MonitorAreaGateExt();
                    tempMonitorExt.ID = -1;
                    tempMonitorExt.Name = "所选店铺总和";
                    tempMonitorExt.ParentID = null;
                    tempMonitorExt.TypeID = 2;
                    tempMonitorExt.IsSelected = true;
                    this.MonitorAreaGateExts.Add(tempMonitorExt);
                }

            }
        }

        public void SelectAreasChanged2(List<area> areas)
        {
            if (areas.Count > 0)
            {
                this.MonitorAreaGateExts2.Clear();
                MonitorAreaGateExt tempMonitorExt;
                if (areas.Count == 1)
                {
                    MonitorAreaGateExt topMonitorExt = new MonitorAreaGateExt();
                    topMonitorExt.ID = areas[0].ID;
                    topMonitorExt.Name = "全部";
                    topMonitorExt.ParentID = areas[0].ParentID;
                    topMonitorExt.TypeID = 1;
                    topMonitorExt.IsSelected = true;
                    this.MonitorAreaGateExts2.Add(topMonitorExt);

                    areas[0].gates.OrderBy(o => o.ID).each(e =>
                    {
                        tempMonitorExt = new MonitorAreaGateExt();
                        tempMonitorExt.ID = e.ID;
                        tempMonitorExt.ParentID = areas[0].ID;
                        tempMonitorExt.Name = e.Name;
                        tempMonitorExt.TypeID = 0;
                        tempMonitorExt.ParentMonitor = topMonitorExt;
                        tempMonitorExt.IsSelected = true;
                        topMonitorExt.Childs.Add(tempMonitorExt);
                        this.MonitorAreaGateExts2.Add(tempMonitorExt);
                    });

                }
                else
                {
                    areas.each(a =>
                    {
                        tempMonitorExt = new MonitorAreaGateExt();
                        tempMonitorExt.ID = a.ID;
                        tempMonitorExt.Name = a.Name;
                        tempMonitorExt.ParentID = a.ParentID;
                        tempMonitorExt.TypeID = 1;
                        tempMonitorExt.IsSelected = true;
                        this.MonitorAreaGateExts2.Add(tempMonitorExt);
                    });

                    tempMonitorExt = new MonitorAreaGateExt();
                    tempMonitorExt.ID = -1;
                    tempMonitorExt.Name = "所选店铺总和";
                    tempMonitorExt.ParentID = null;
                    tempMonitorExt.TypeID = 2;
                    tempMonitorExt.IsSelected = true;
                    this.MonitorAreaGateExts2.Add(tempMonitorExt);
                }

            }
        }

        public bool IsConditionSelected()
        {
            bool isSelected = true;

            var selectedArea = this.AreaExtends.Where(a => a.IsSelected);

            if (selectedArea.Any())
            {
                var selectGates = this.MonitorAreaGateExts.Where(m => m.IsSelected);
                if (selectGates.Any())
                {
                    isSelected = true;
                }
                else
                {
                    isSelected = false;
                }
            }
            else
            {
                isSelected = false;
            }

            return isSelected;
        }

        public bool IsConditionSelected2()
        {
            bool isSelected = true;

            var selectedArea = this.AreaExtends2.Where(a => a.IsSelected);

            if (selectedArea.Any())
            {
                var selectGates = this.MonitorAreaGateExts2.Where(m => m.IsSelected);
                if (selectGates.Any())
                {
                    isSelected = true;
                }
                else
                {
                    isSelected = false;
                }
            }
            else
            {
                isSelected = false;
            }

            return isSelected;
        }
        #endregion

        #region 多时段按日序列对比

        public void RefreshDurationPassenger(bool isIn, DateTime startTime1, DateTime endTime1, DateTime startTime2, DateTime endTime2)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }

            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            this.CurveTitle = GetDurationCurveTitle(isSingleArea, isIn);

            var getDurationPassengerQuery = m_Context.GetPassengerflowbyHourByTimeQuery(monitorAreaIDs, startTime1, endTime1);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var firstDurationPassengers = GetHistoryPassengerFlow(isSingleArea, s.Entities, startTime1, endTime1);

                    var sceondDuraionPassengerQuery = m_Context.GetPassengerflowbyHourByTimeQuery(monitorAreaIDs, startTime2, endTime2);
                    var loadSecondPassengerQuery = m_Context.Load(sceondDuraionPassengerQuery, (ss) => {

                        if (!ss.HasError)
                        {
                            var secondDurationPassengers = GetHistoryPassengerFlow(isSingleArea, ss.Entities, startTime2, endTime2);
                            int index = 0;
                            string firstDateStr = string.Empty;
                            string secDateStr = string.Empty;
                            if (firstDurationPassengers.Count >= secondDurationPassengers.Count)
                            {
                                while (index < firstDurationPassengers.Count)
                                {
                                    firstDateStr = string.Format("{0:MM-dd}", firstDurationPassengers[index].HistoryTime);
                                    if (index < secondDurationPassengers.Count)
                                    {
                                        secDateStr = string.Format("{0:MM-dd}", secondDurationPassengers[index].HistoryTime);
                                    }
                                    else
                                    {
                                        secDateStr = string.Empty;
                                    }
                                    firstDurationPassengers[index].DisplayValue = firstDateStr + "\r\n" + secDateStr;
                                    if (index < secondDurationPassengers.Count)
                                    {
                                        secondDurationPassengers[index].DisplayValue = firstDateStr + "\r\n" + secDateStr;
                                    }
                                    index++;
                                }
                            }
                            else
                            {
                                while (index < secondDurationPassengers.Count)
                                {
                                    secDateStr = string.Format("{0:MM-dd}", secondDurationPassengers[index].HistoryTime);
                                    if (index < firstDurationPassengers.Count)
                                    {
                                        firstDateStr = string.Format("{0:MM-dd}", firstDurationPassengers[index].HistoryTime);
                                    }
                                    else
                                    {
                                        firstDateStr = string.Empty;
                                    }
                                    secondDurationPassengers[index].DisplayValue = firstDateStr + "\r\n" + secDateStr;
                                    if (index < firstDurationPassengers.Count)
                                    {
                                        firstDurationPassengers[index].DisplayValue = firstDateStr + "\r\n" + secDateStr;
                                    }
                                    index++;
                                }
                            }


                            if (AppendHistoryPassengerFlow != null)
                            {
                                AppendHistoryPassengerFlow(this.CurveTitle,isIn, firstDurationPassengers, secondDurationPassengers);
                            }
                        }
                    
                    },true);
                }
            }, true);
        }

        private string GetDurationCurveTitle(bool isSingleArea,bool isIn)
        {
            string title = string.Empty;
            string title2 = isIn? "进客流":"出客流";
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        title = GetAreaName(topAreaGate.ID) +" 所有门面 " + title2 + "对比分析图";
                    }
                    else
                    {
                        title = GetAreaName(topAreaGate.ID) + " 所选门面 " + title2 + "对比分析图";
                    }
                }
            }
            else
            {
                title ="所选店铺 " + title2 + "对比分析图";
            }
            return title;
        }

        private List<HistoryPassengerFlow> GetHistoryPassengerFlow(bool isSingleArea, IEnumerable<passengerflowbymin> entities, DateTime startTime, DateTime endTime)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbymin> tempPassengerFlows = new List<passengerflowbymin>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            historyPassengerFlows = ConvertToDurationHistoryPassengerFlow(tempPassengerFlows, startTime, endTime);

            return historyPassengerFlows;
        }

        #endregion

        #region 任意时段客流分布统计

        public void RefreshAnyDurationPassengerStatistic(bool isIn, DateTime startTime, DateTime endTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }

            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            this.CurveTitle = GetAnyDurationCurveTitle(isSingleArea, isIn, startTime, endTime);

            var getDurationPassengerQuery = m_Context.GetPassengerflowbySpecifiedTimeQuery(monitorAreaIDs, 30,startTime, endTime);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var durationPassengers = GetAnyDurationHistoryPassengerFlow(isSingleArea, s.Entities, startTime, endTime);

                    if (AppendHistoryPassengerFlow != null)
                    {

                        AppendHistoryPassengerFlow(this.CurveTitle, isIn, CompoundHistoryPassengerFlow(false, durationPassengers, startTime, endTime), null);
                    }
                }
            }, true);
        }

        private string GetAnyDurationCurveTitle(bool isSingleArea, bool isIn,DateTime startTime, DateTime endTime)
        {
           
            string title = string.Empty;
            if (startTime.Year == endTime.Year && startTime.Month == endTime.Month && startTime.Day == endTime.Day)
            {
                title = startTime.ToShortDateString();
            }
            else
            {
                title = startTime.ToShortDateString() + "至" + endTime.ToShortDateString();
            }

            string title2 = "{0}";
            title = title + " " + title2;
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        title = title + " (" + GetAreaName(topAreaGate.ID) + " 所有门面)";
                    }
                    else
                    {
                        title = title+" ("+GetAreaName(topAreaGate.ID) + " 所选门面 )";
                    }
                }
            }
            else
            {
                title = title + "(所选店铺)";
            }
            return title;
        }

        private List<HistoryPassengerFlow> GetAnyDurationHistoryPassengerFlow(bool isSingleArea,
                                                                              IEnumerable<passengerflowbymin> entities,
                                                                              DateTime startTime,
                                                                              DateTime endTime)
        {

            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbymin> tempPassengerFlows = new List<passengerflowbymin>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            historyPassengerFlows = ConvertHistoryPassengerFlow(tempPassengerFlows,30, startTime, endTime,null);

            return historyPassengerFlows;
        
        }

        #endregion

        #region 任意时段客流分布对比

        private string GetAnyDurationCompareTitle(bool isSingleArea, DateTime startTime, DateTime endTime,bool isArea1)
        {

            string title = string.Empty;
            if (startTime.Year == endTime.Year && startTime.Month == endTime.Month && startTime.Day == endTime.Day)
            {
                title = startTime.ToShortDateString();
            }
            else
            {
                title = startTime.ToShortDateString() + "至" + endTime.ToShortDateString();
            }

            if (isSingleArea)
            {
                var topAreaGate = isArea1 ? this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault() :
                                           this.MonitorAreaGateExts2.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        title = title + " (" + GetAreaName(topAreaGate.ID) + " 所有门面)";
                    }
                    else
                    {
                        title = title + " (" + GetAreaName(topAreaGate.ID) + " 所选门面 )";
                    }
                }
            }
            else
            {
                title = title + "(所选店铺)";
            }
            return title;
        }

        public void RefreshAnyDurationPassengerCompare(bool isIn,
                                                       DateTime startTime1,
                                                       DateTime endTime1,
                                                       bool isAvg1,
                                                       DateTime startTime2,
                                                       DateTime endTime2,
                                                       bool isAvg2,
                                                       List<DayOfWeek> enableWeeks1,
                                                       List<DayOfWeek> enableWeeks2)
        {

            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }

            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;

            var selectAreaExt2 = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs2 = new List<int>();
            selectAreaExt2.each(s => { monitorAreaIDs2.Add(s.ID); });
            bool isSingleArea2 = monitorAreaIDs2.Count == 1 ? true : false;

            string title = GetAnyDurationCompareTitle(isSingleArea, startTime1, endTime1, true) + "," +
                            GetAnyDurationCompareTitle(isSingleArea2, startTime2, endTime2, false);

            var getDurationPassengerQuery = m_Context.GetPassengerflowbySpecifiedTimeQuery(monitorAreaIDs,30, startTime1, endTime1);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var firstDurationPassengers = GetAnyDurationCompareHistoryPassengerFlow(isSingleArea, s.Entities, startTime1, endTime1,enableWeeks1);

                    var sceondDuraionPassengerQuery = m_Context.GetPassengerflowbySpecifiedTimeQuery(monitorAreaIDs2,30, startTime2, endTime2);
                    var loadSecondPassengerQuery = m_Context.Load(sceondDuraionPassengerQuery, (ss) =>
                    {

                        if (!ss.HasError)
                        {
                            var secondDurationPassengers = GetAnyDurationCompareHistoryPassengerFlow2(isSingleArea2, ss.Entities, startTime2, endTime2,enableWeeks2);

                            if (AppendHistoryPassengerFlow != null)
                            {
                                AppendHistoryPassengerFlow(title, isIn,
                                                           CompoundHistoryPassengerFlow(isAvg1, firstDurationPassengers, startTime1, endTime1),
                                                           CompoundHistoryPassengerFlow(isAvg2, secondDurationPassengers, startTime2, endTime2));
                            }
                        }

                    }, true);
                }
            }, true);


        }


        private List<HistoryPassengerFlow> GetAnyDurationCompareHistoryPassengerFlow(bool isSingleArea,
                                                                                     IEnumerable<passengerflowbymin> entities,
                                                                                     DateTime startTime,
                                                                                     DateTime endTime,
                                                                                     List<DayOfWeek> enbaleWeeks)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbymin> tempPassengerFlows = new List<passengerflowbymin>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            historyPassengerFlows = ConvertHistoryPassengerFlow(tempPassengerFlows, 30, startTime, endTime, enbaleWeeks);

            return historyPassengerFlows;
        }

        private List<HistoryPassengerFlow> GetAnyDurationCompareHistoryPassengerFlow2(bool isSingleArea,
                                                                                   IEnumerable<passengerflowbymin> entities,
                                                                                   DateTime startTime,
                                                                                   DateTime endTime,
                                                                                   List<DayOfWeek> enbaleWeeks)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbymin> tempPassengerFlows = new List<passengerflowbymin>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts2.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts2.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            historyPassengerFlows = ConvertHistoryPassengerFlow(tempPassengerFlows, 30, startTime, endTime, enbaleWeeks);

            return historyPassengerFlows;
        }


        private List<HistoryPassengerFlow> CompoundHistoryPassengerFlow(bool isAvg, List<HistoryPassengerFlow> historyPassengerFlow, DateTime startTime, DateTime endTime)
        {
            List<HistoryPassengerFlow> computedHistoryPassengerFlow = new List<HistoryPassengerFlow>();

            // DateTime startTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);
            // DateTime endTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59);
            int lastInCount = 0;
            int lastOutCount = 0;
            while (startTime < endTime)
            {
                HistoryPassengerFlow tempPassgnegerFlow = new HistoryPassengerFlow();
                //historyPassengerFlow.DisplayTitle = dtRangeStart.ToShortDateString() + " 至 " + dtRangeEnd.ToShortDateString();
                tempPassgnegerFlow.HistoryTime = startTime;
                tempPassgnegerFlow.DisplayValue = string.Format("{0:HH:mm}", startTime);
                IEnumerable<int> inCounts = from t in historyPassengerFlow
                                             where t.HistoryTime.Hour == startTime.Hour && 
                                                   t.HistoryTime.Minute == startTime.Minute && 
                                                   t.HistoryTime.Second == startTime.Second
                                             select t.InCount;
                IEnumerable<int> outCounts = from t in historyPassengerFlow
                                             where t.HistoryTime.Hour == startTime.Hour &&
                                                 t.HistoryTime.Minute == startTime.Minute &&
                                                 t.HistoryTime.Second == startTime.Second
                                              select t.OutCount;
                IEnumerable<int> strandedCount = from t in historyPassengerFlow
                                                 where t.HistoryTime.Hour == startTime.Hour &&
                                                  t.HistoryTime.Minute == startTime.Minute &&
                                                  t.HistoryTime.Second == startTime.Second
                                                 select t.StrandedCount;
                tempPassgnegerFlow.InCount = inCounts.Any() ? (isAvg ? Convert.ToInt32(inCounts.Average()) : inCounts.Sum()) : 0;
                tempPassgnegerFlow.OutCount = outCounts.Any() ? (isAvg ? Convert.ToInt32(outCounts.Average()) : outCounts.Sum()) : 0;

                lastInCount += tempPassgnegerFlow.InCount;
                lastOutCount += tempPassgnegerFlow.OutCount;
                tempPassgnegerFlow.AccumulateInCount = lastInCount;
                tempPassgnegerFlow.AccumulateOutCount = lastOutCount;

                tempPassgnegerFlow.StrandedCount = strandedCount.Any() ? (isAvg ? Convert.ToInt32(strandedCount.Average()) : strandedCount.Sum()) : 0;
                computedHistoryPassengerFlow.Add(tempPassgnegerFlow);
                startTime = startTime.AddMinutes(30);

            }

            return computedHistoryPassengerFlow;
        }

        public List<HistoryPassengerFlow> CompoundHistoryPassengerAndPos(bool isAvg, List<HistoryPassengerFlow> historyPassengerFlow, List<posbymin> possbyMins)
        {
            List<HistoryPassengerFlow> computedHistoryPassengerFlow = new List<HistoryPassengerFlow>();

            DateTime startTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);
            DateTime endTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59);
            decimal percent = 0;
            while (startTime < endTime)
            {
                HistoryPassengerFlow tempPassgnegerFlow = new HistoryPassengerFlow();
                //historyPassengerFlow.DisplayTitle = dtRangeStart.ToShortDateString() + " 至 " + dtRangeEnd.ToShortDateString();
                tempPassgnegerFlow.HistoryTime = startTime;
                tempPassgnegerFlow.DisplayValue = string.Format("{0:HH:mm}", startTime);
                IEnumerable<int> inCounts = from t in historyPassengerFlow
                                            where t.HistoryTime.Hour == startTime.Hour &&
                                                  t.HistoryTime.Minute == startTime.Minute &&
                                                  t.HistoryTime.Second == startTime.Second
                                            select t.InCount;
                IEnumerable<int> outCounts = from t in historyPassengerFlow
                                             where t.HistoryTime.Hour == startTime.Hour &&
                                                 t.HistoryTime.Minute == startTime.Minute &&
                                                 t.HistoryTime.Second == startTime.Second
                                             select t.OutCount;
                IEnumerable<int> strandedCount = from t in historyPassengerFlow
                                                 where t.HistoryTime.Hour == startTime.Hour &&
                                                  t.HistoryTime.Minute == startTime.Minute &&
                                                  t.HistoryTime.Second == startTime.Second
                                                 select t.StrandedCount;
                IEnumerable<int> tradeMoneys = from t in possbyMins
                                               where t.dt.Hour == startTime.Hour &&
                                                 t.dt.Minute == startTime.Minute &&
                                                 t.dt.Second == startTime.Second
                                               select t.TradeMoney;
                IEnumerable<int> tradeCounts = from t in possbyMins
                                               where t.dt.Hour == startTime.Hour &&
                                                 t.dt.Minute == startTime.Minute &&
                                                 t.dt.Second == startTime.Second
                                               select t.TradeCount;

                tempPassgnegerFlow.InCount = inCounts.Any() ? (isAvg ? Convert.ToInt32(inCounts.Average()) : inCounts.Sum()) : 0;
                tempPassgnegerFlow.OutCount = outCounts.Any() ? (isAvg ? Convert.ToInt32(outCounts.Average()) : outCounts.Sum()) : 0;

                tempPassgnegerFlow.StrandedCount = strandedCount.Any() ? (isAvg ? Convert.ToInt32(strandedCount.Average()) : strandedCount.Sum()) : 0;

                tempPassgnegerFlow.TradeCount = tradeCounts.Any() ? (isAvg ? Convert.ToInt32(tradeCounts.Average()) : tradeCounts.Sum()) : 0;
                tempPassgnegerFlow.TradeMoney = tradeMoneys.Any() ? (isAvg ? Convert.ToInt32(tradeMoneys.Average()) : tradeMoneys.Sum()) : 0;

                percent = tempPassgnegerFlow.TradeCount > 0 ? (decimal)tempPassgnegerFlow.TradeMoney / tempPassgnegerFlow.TradeCount: 0;
                percent = Math.Round(percent, 2);
                tempPassgnegerFlow.AvgTradeMoney = percent.ToString();

                percent = tempPassgnegerFlow.InCount > 0 ? ((decimal)tempPassgnegerFlow.TradeCount / tempPassgnegerFlow.InCount) * 100 : 0;
                percent = Math.Round(percent, 2);

                tempPassgnegerFlow.SalePercent = Convert.ToDouble(percent/100);

                computedHistoryPassengerFlow.Add(tempPassgnegerFlow);
                startTime = startTime.AddMinutes(30);

            }

            return computedHistoryPassengerFlow;
        }

        #endregion

        #region 任意时段提袋率分析

        public void RefreshDurationPassengerAndPos(bool isIn, DateTime startTime, DateTime endTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }

            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            this.CurveTitle = GetAnyDurationCurveTitle(isSingleArea, isIn, startTime, endTime);

            var getDurationPassengerQuery = m_Context.GetPassengerflowbySpecifiedTimeQuery(monitorAreaIDs, 30, startTime, endTime);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var durationPassengers = GetAnyDurationHistoryPassengerFlow(isSingleArea, s.Entities, startTime, endTime);

                    var getPosQuery = m_Context.GetPosDataBySpecifiedTimeQuery(monitorAreaIDs, 30, startTime, endTime);
                    var lodPosQuery = m_Context.Load(getPosQuery, (t) => {

                        if (AppendHistoryPassengerFlow != null)
                        {

                            AppendHistoryPassengerFlow(this.CurveTitle, isIn, CompoundHistoryPassengerAndPos(false, durationPassengers, t.Entities.ToList()), null);
                        }
                    
                    
                    },true);

                }
            }, true);
        }

        #endregion

        #region 平均滞留时间统计表

        public void RefreshPassengerflowTimeStamp(bool isIn, DateTime startTime, DateTime endTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }

            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            //this.CurveTitle = GetAnyDurationCurveTitle(isSingleArea, isIn, startTime, endTime);

            var getPassengerStampQuery = m_Context.GetPassengerflowStampQuery(monitorAreaIDs,
                                                                                 FayshineManager.BussinessStartTime,
                                                                                 FayshineManager.BussinessEndTime,
                                                                                 startTime,
                                                                                 endTime);
            var loadPassgnerStampQuery = m_Context.Load(getPassengerStampQuery, (s) =>
            {
                if (!s.HasError)
                {
                    if (AppendHistoryPassengerFlow != null)
                    {
                        AppendHistoryPassengerFlow(string.Empty, true, ConvertDayHistoryPassengerStamps(s.Entities.ToList(), startTime, endTime), null);
                    }
                }
            }, true);
        }

        #endregion

        #region 日最繁忙15分钟统计

        private string GetCheckedGatesText()
        {
            string sRet = string.Empty;

            if (m_checkedGates != null && m_checkedGates.Count > 0)
            {
                if (m_checkedGates.Count == MonitorAreaGateExts.Count)
                {
                    sRet = "所有";
                }
                else
                {
                    StringBuilder sb = new StringBuilder();
                    m_checkedGates.ForEach(g =>
                        {
                            sb.AppendFormat(", {0}", g.Name);
                        });
                    sRet = sb.ToString().TrimStart(",".ToCharArray());
                }
            }

            return sRet;
        }

        private string GetCheckedAreasText()
        {
            string sRet = string.Empty;

            if (m_checkedAreas != null && m_checkedAreas.Count  > 0)
            {
                if (m_checkedAreas.Count == AreaExtends.Count)
                {
                    sRet = string.Format("(店铺 -- 所有 -- )");
                }
                else if (m_checkedAreas.Count == 1)
                {
                    // Need list gates
                    string gates = GetCheckedGatesText();
                    sRet = string.Format("(店铺 -- {0} -- 门 -- {1} --)", m_checkedAreas[0].Name, gates);
                }
                else if (m_checkedAreas.Count > 1)
                {
                    // Just list areas
                    StringBuilder sb = new StringBuilder();
                    m_checkedAreas.ForEach(a =>
                    {
                        sb.AppendFormat(", {0}", a.Name);
                    });
                    sRet = sb.ToString().TrimStart(",".ToCharArray());
                    sRet = string.Format("(店铺 -- {0} -- )", sRet);
                }
                else
                {
                    Debug.Assert(false, "No area checked");
                }
            }

            return sRet;
        }

        private string GetBusy15MinsCurveTitle(bool isSingleArea, int type, DateTime startTime)
        {

            string sRet =startTime.ToShortDateString();

            string sCat = "进客流";
            if (type == 1)
            {
                sCat = "出客流";
            }
            else if (type == 2)
            {
                sCat = "进出客流";
            }
                       
            string sCheckedAreas = GetCheckedAreasText();
           
            sRet = string.Format("{0} {1} 每小时最繁忙15分钟统计 {2}",
                startTime.ToShortDateString(), sCat, sCheckedAreas);

            return sRet;
        }

        public void RefreshBusy15MinsPassengerStatistics(int type,DateTime startTime, DateTime endTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }

            List<int> monitorAreaIDs = new List<int>();
            m_checkedAreas.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            this.CurveTitle = GetBusy15MinsCurveTitle(isSingleArea, type, startTime);

            var getDurationPassengerQuery = m_Context.GetPassengerflowbySpecifiedTimeQuery(monitorAreaIDs, 15, startTime, endTime);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var durationPassengers = GetBusy15MinsHistoryPassengerFlow(type,isSingleArea, s.Entities, startTime, endTime);

                    if (AppendHistoryPassengerFlow != null)
                    {
                        AppendHistoryPassengerFlow(this.CurveTitle, true, durationPassengers, null);
                    }
                }
            }, true);
        }

        private List<HistoryPassengerFlow> GetBusy15MinsHistoryPassengerFlow(int type, bool isSingleArea, IEnumerable<passengerflowbymin> entities,
                                                       DateTime startTime, DateTime endTime)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbymin> tempPassengerFlows = new List<passengerflowbymin>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            historyPassengerFlows = ConvertHistoryPassengerFlow(tempPassengerFlows, 15, startTime, endTime, null);

            return ConvertToBusy15MinsHistoryPassengerFlow(type, historyPassengerFlows, startTime, endTime);
        }

        private List<HistoryPassengerFlow> ConvertToBusy15MinsHistoryPassengerFlow(int type,List<HistoryPassengerFlow> passengerFlows,
                                                                                   DateTime startTime, DateTime endTime)
        {
            List<HistoryPassengerFlow> busy15MinsHistory = new List<HistoryPassengerFlow>();

            HistoryPassengerFlow temp = null;
            DateTime tempEndTime = startTime.AddHours(1);
            List<HistoryPassengerFlow> tmpHPF;

            int max;
            
            while (startTime < endTime)
            {
                tmpHPF = passengerFlows.Where(p => p.HistoryTime.Hour == startTime.Hour).ToList();

                if (tmpHPF.Any())
                {
                    temp = new HistoryPassengerFlow();

                    if (type == 1)
                    {
                        max = tmpHPF.Select(t => t.OutCount).Max();
                        temp.HistoryTime = tmpHPF.Where(t => t.OutCount == max).FirstOrDefault().HistoryTime;
                        temp.OutCount = max;
                    }
                    else if (type == 2)
                    {
                        max = tmpHPF.Select(t => t.AllInOut).Max();
                        temp.HistoryTime = tmpHPF.Where(t => t.AllInOut == max).FirstOrDefault().HistoryTime;
                        temp.AllInOut = max;
                    }
                    else
                    {
                        max = tmpHPF.Select(t => t.InCount).Max();
                        temp.HistoryTime = tmpHPF.Where(t => t.InCount == max).FirstOrDefault().HistoryTime;
                        temp.InCount = max;
                    }
               
                   busy15MinsHistory.Add(temp);
               }
                startTime = tempEndTime;
                tempEndTime = startTime.AddHours(1);
            }
            return busy15MinsHistory;
        }

        #endregion

        #region 日每5分钟客流统计

        private string GetDay5MinsCurveTitle(bool isSingleArea, DateTime startTime)
        {
            string sCheckedAreas = GetCheckedAreasText();

            string sRet = string.Format("{0} 每5分钟分布图 {1}",
                startTime.ToShortDateString() + "{0}", sCheckedAreas);

            return sRet;
        }

        public void RefreshDay5MinsPassengerFlows(DateTime startTime, DateTime endTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }

            List<int> monitorAreaIDs = new List<int>();
            m_checkedAreas.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            this.CurveTitle = GetDay5MinsCurveTitle(isSingleArea, startTime);

            var getDurationPassengerQuery = m_Context.GetPassengerflowbyMinByTimeQuery(monitorAreaIDs, startTime, endTime);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var durationPassengers = GetDay5MinsHistoryPassengerFlow(isSingleArea, s.Entities, startTime, endTime);

                    if (AppendHistoryPassengerFlow != null)
                    {
                        AppendHistoryPassengerFlow(this.CurveTitle,false, durationPassengers, null);
                    }
                }
            }, true);
        }

        private List<HistoryPassengerFlow> GetDay5MinsHistoryPassengerFlow(bool isSingleArea,
                                                                              IEnumerable<passengerflowbymin> entities,
                                                                              DateTime startTime,
                                                                              DateTime endTime)
        {

            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbymin> tempPassengerFlows = new List<passengerflowbymin>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            historyPassengerFlows = ConvertHistoryPassengerFlow(tempPassengerFlows, 5, startTime, endTime, null);

            return historyPassengerFlows;

        }

        #endregion

        #region 日分时段客流统计

        private string GetDayDurationCurveTitle(bool isSingleArea, DateTime startTime)
        {

            string title = startTime.ToShortDateString();

            string title2 = "{0}";
            title = title + " " + title2 + "分布图";

            string sCheckedAreas = GetCheckedAreasText();
            title = title + sCheckedAreas;
            return title;
        }

        /// <summary>
        /// 日分时段, 每半小时一统计单位
        /// </summary>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        public void RefreshDayDurationPassengerFlows(DateTime startTime, DateTime endTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }

            List<int> monitorAreaIDs = new List<int>();
            m_checkedAreas.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            this.CurveTitle = GetDayDurationCurveTitle(isSingleArea, startTime);

            var getDurationPassengerQuery = m_Context.GetPassengerflowbySpecifiedTimeQuery(monitorAreaIDs,30, startTime, endTime);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var durationPassengersAll = GetDurationHistoryPassengerFlow(isSingleArea, s.Entities, startTime, endTime,30);
                    Dictionary<AreaExtend, List<HistoryPassengerFlow>> dtarea2HPFs = new Dictionary<AreaExtend, List<HistoryPassengerFlow>>();
                    if (!isSingleArea)
                    {
                        List<passengerflowbymin> pfbyMinbyArea;
                        List<HistoryPassengerFlow> hpfByArea;
                        List<int> gateIDs;
                        foreach (AreaExtend area in m_checkedAreas)
                        {
                            gateIDs = GetGateIDsByArea(area.ID);
                            pfbyMinbyArea = s.Entities.Where(e => gateIDs.Contains(e.gateID)).ToList();
                            hpfByArea = GetDurationHistoryPassengerFlow(false, pfbyMinbyArea, startTime, endTime, 30);
                            dtarea2HPFs.Add(area, hpfByArea);
                        }
                    }

                    if (AppendDayDurationHistoryPassenger != null)
                    {
                        AppendDayDurationHistoryPassenger(this.CurveTitle, false, durationPassengersAll, dtarea2HPFs);
                    }
                }
            }, true);
        }

        #endregion

        #region 日各通道客流统计

        public void RefreshAllShopPassengerFlows(DateTime startTime, DateTime endTime)
        {

            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }

            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            //bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;

            var getDurationPassengerQuery = m_Context.GetPassengerflowbySpecifiedTimeQuery(monitorAreaIDs, 30, startTime, endTime);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var durationPassengers = GetDurationHistoryPassengerFlow(true, s.Entities, startTime, endTime, 60);
                    this.TempPassengerFlowbyMIn = s.Entities.ToList();
                    if (AppendHistoryPassengerFlow != null)
                    {
                        AppendHistoryPassengerFlow(this.CurveTitle, false, durationPassengers, null);
                    }
                }
            }, true);
        }

        public List<HistoryPassengerFlow> GetDayPassengerFlowByGateID(int gateID, DateTime startTime, DateTime endTime, int duration)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbymin> tempPassengerFlows = new List<passengerflowbymin>();

            tempPassengerFlows = this.TempPassengerFlowbyMIn.Where(entity => gateID == entity.gateID).ToList();

            historyPassengerFlows = ConvertHistoryPassengerFlow(tempPassengerFlows, duration, startTime, endTime, null);

            return historyPassengerFlows;
        }

        public List<HistoryPassengerFlow> GetDayPassengerFlowByAreaID(int areaID, DateTime startTime, DateTime endTime, int duration)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbymin> tempPassengerFlows = new List<passengerflowbymin>();

            List<int> ids = new List<int>();
            ids = GetGateIDsByArea(areaID);
            tempPassengerFlows = this.TempPassengerFlowbyMIn.Where(entity => ids.Contains(entity.gateID)).ToList();
            historyPassengerFlows = ConvertHistoryPassengerFlow(tempPassengerFlows, duration, startTime, endTime, null);

            return historyPassengerFlows;
        }

        public List<HistoryPassengerFlow> GetDayAllPassengerFlow(DateTime startTime, DateTime endTime, int duration)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();

            historyPassengerFlows = ConvertHistoryPassengerFlow(this.TempPassengerFlowbyMIn, duration, startTime, endTime, null);

            return historyPassengerFlows;
        }

        #endregion

        #region 日各区域客流统计

        public void RefreshAllAreaPassengerFlows(DateTime startTime, DateTime endTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }
            this.AreaExtends.each(a => a.IsSelected = true);
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            //bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;

            var getDurationPassengerQuery = m_Context.GetPassengerflowbySpecifiedTimeQuery(monitorAreaIDs, 30, startTime, endTime);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var durationPassengers = GetDurationHistoryPassengerFlow(true, s.Entities, startTime, endTime, 60);
                    this.TempPassengerFlowbyMIn = s.Entities.ToList();
                    if (AppendHistoryPassengerFlow != null)
                    {
                        AppendHistoryPassengerFlow(this.CurveTitle, false, durationPassengers, null);
                    }
                }
            }, true);
        }

        #endregion

        public void UpdateCheckedAreas()
        {
            m_checkedAreas = this.AreaExtends.Where(a => a.IsSelected).ToList();
            m_checkedGates = this.MonitorAreaGateExts.Where(g => g.IsSelected).ToList();
        }

        #region Private Methods

        private List<HistoryPassengerFlow> ConvertDayHistoryPassengerStamps(List<passengerflowtimestamp> passengerflowStamps, DateTime startTime, DateTime endTime)
        {
            List<HistoryPassengerFlow> daysPassengerStamps = new List<HistoryPassengerFlow>();

            while (startTime < endTime)
            {
                HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();

                historyPassengerFlow.HistoryTime = startTime;
                historyPassengerFlow.DisplayTitle = string.Format("{0:d}", startTime);

                IEnumerable<int> inCounts = from t in passengerflowStamps
                                            where t.DT.Month == startTime.Month && t.DT.Year == startTime.Year && t.DT.Day == startTime.Day && t.IsIn == true
                                            select t.Count;
                IEnumerable<int> outCounts = from t in passengerflowStamps
                                             where t.DT.Month == startTime.Month && t.DT.Year == startTime.Year && t.DT.Day == startTime.Day && t.IsIn == false
                                             select t.Count;

                IEnumerable<double> inTimeStamp = from t in passengerflowStamps
                                                where t.DT.Month == startTime.Month && t.DT.Year == startTime.Year && t.DT.Day == startTime.Day && t.IsIn == true
                                                select t.Stamp;
                IEnumerable<double> outTimeStamp = from t in passengerflowStamps
                                                  where t.DT.Month == startTime.Month && t.DT.Year == startTime.Year && t.DT.Day == startTime.Day && t.IsIn == false
                                                  select t.Stamp;

                historyPassengerFlow.InCount = inCounts.Sum();
                historyPassengerFlow.OutCount = outCounts.Sum();
                historyPassengerFlow.StrandedCount = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                if (historyPassengerFlow.StrandedCount != 0)
                {
                    historyPassengerFlow.StrandedMinutes = Convert.ToInt32(((outTimeStamp.Sum() - inTimeStamp.Sum()) / 60000) / historyPassengerFlow.StrandedCount);
                }
                else
                {
                    historyPassengerFlow.StrandedMinutes = 0;
                }
                daysPassengerStamps.Add(historyPassengerFlow);
                startTime = startTime.AddDays(1);

            }

            HistoryPassengerFlow historyPassengerFlow2 = new HistoryPassengerFlow();

            historyPassengerFlow2.DisplayTitle = "累计平均";
            historyPassengerFlow2.StrandedMinutes = daysPassengerStamps.Sum(d => d.StrandedMinutes);

            daysPassengerStamps.Add(historyPassengerFlow2);

            return daysPassengerStamps;
        }

        public List<int> GetGateIDsByArea(int areaID)
        {
            List<int> ids = new List<int>();

            var area = this.AreaExtends.Where(a => a.ID == areaID).FirstOrDefault().Tag as area;
            if (area != null)
            {
                area.gates.each(g => { ids.Add(g.ID); });
            }
            return ids;
        }

        public string GetGateName(int id)
        {
            string title = string.Empty;

            var a = this.MonitorAreaGateExts.Where(m => m.ID == id).FirstOrDefault();
            if (a != null)
            {
                title = a.Name;
            }

            return title;
        }

        public string GetAreaName(int areaID)
        {
            return this.AreaExtends.Where(a => a.ID == areaID).First().Name;
        }

        private List<HistoryPassengerFlow> ConvertToDurationHistoryPassengerFlow(List<passengerflowbymin> passengerflows, DateTime dtRangeStart, DateTime dtRangeEnd)
        {
            List<HistoryPassengerFlow> dayRealTimePassengerFlow = new List<HistoryPassengerFlow>();
            DateTime startTime = dtRangeStart;
            while (startTime <= dtRangeEnd)
            {
                DateTime endTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, 23, 59, 59);

                HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();
                historyPassengerFlow.DisplayTitle = dtRangeStart.ToShortDateString() + " 至 " + dtRangeEnd.ToShortDateString();
                historyPassengerFlow.HistoryTime = startTime;
                IEnumerable<int?> inCounts = from t in passengerflows
                                             where t.dt >= startTime && t.dt < endTime && t.isIn == true
                                               select t.count;
                IEnumerable<int?> outCounts = from t in passengerflows
                                              where t.dt >= startTime && t.dt < endTime && t.isIn == false
                                                select t.count;

                historyPassengerFlow.InCount = inCounts.Sum().Value;
                historyPassengerFlow.OutCount = outCounts.Sum().Value;

                dayRealTimePassengerFlow.Add(historyPassengerFlow);

                startTime = startTime.AddDays(1); 
            }
            return dayRealTimePassengerFlow;
        }

        private List<HistoryPassengerFlow> ConvertHistoryPassengerFlow(List<passengerflowbymin> passengerflows,
                                                                        int minsDuration, 
                                                                        DateTime dtRangeStart, 
                                                                        DateTime dtRangeEnd,
                                                                        List<DayOfWeek> enableWeeks)
        {
            List<HistoryPassengerFlow> dayRealTimePassengerFlow = new List<HistoryPassengerFlow>();
            DateTime startTime = dtRangeStart;
            int lastInCount = 0;
            int lastOutCount = 0;
            bool isIncludeWeek = true;
            while (startTime < dtRangeEnd)
            {
                if (enableWeeks != null && enableWeeks.Count > 0)
                {
                    if (enableWeeks.Contains(startTime.DayOfWeek))
                    {
                        isIncludeWeek = true;
                    }
                    else
                    {
                        isIncludeWeek = false;
                    }
                }
                else
                {
                    isIncludeWeek = true;
                }
                if (isIncludeWeek)
                {
                    HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();
                    //historyPassengerFlow.DisplayTitle = dtRangeStart.ToShortDateString() + " 至 " + dtRangeEnd.ToShortDateString();
                    historyPassengerFlow.HistoryTime = startTime;
                    IEnumerable<int?> inCounts = from t in passengerflows
                                                 where t.dt == startTime && t.isIn == true
                                                 select t.count;
                    IEnumerable<int?> outCounts = from t in passengerflows
                                                  where t.dt == startTime && t.isIn == false
                                                  select t.count;

                    historyPassengerFlow.InCount = inCounts.Sum().Value;
                    historyPassengerFlow.OutCount = outCounts.Sum().Value;

                    lastInCount += historyPassengerFlow.InCount;
                    lastOutCount += historyPassengerFlow.OutCount;
                    historyPassengerFlow.AccumulateInCount = lastInCount;
                    historyPassengerFlow.AccumulateOutCount = lastOutCount;

                    historyPassengerFlow.StrandedCount = historyPassengerFlow.AccumulateInCount - historyPassengerFlow.AccumulateOutCount;
                    historyPassengerFlow.AllInOut = historyPassengerFlow.InCount + historyPassengerFlow.OutCount;
                    historyPassengerFlow.Differ = historyPassengerFlow.AccumulateInCount - historyPassengerFlow.AccumulateOutCount;

                    //lastInCount = historyPassengerFlow.AccumulateInCount;
                    //lastOutCount = historyPassengerFlow.AccumulateOutCount;

                    dayRealTimePassengerFlow.Add(historyPassengerFlow);
                }
                startTime = startTime.AddMinutes(minsDuration);
            }
            return dayRealTimePassengerFlow;
        }


        private List<HistoryPassengerFlow> GetDurationHistoryPassengerFlow(bool isSingleArea,
                                                                          IEnumerable<passengerflowbymin> entities,
                                                                          DateTime startTime,
                                                                          DateTime endTime,
                                                                          int duration)
        {

            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbymin> tempPassengerFlows = new List<passengerflowbymin>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }
            
            historyPassengerFlows = ConvertHistoryPassengerFlow(tempPassengerFlows, duration, startTime, endTime, null);

            //if (m_checkedAreas.Count > 1)
            //{
                
            //}

            return historyPassengerFlows;

        }
        #endregion

        #region INotifyPropertyChanged Interface

        public event PropertyChangedEventHandler PropertyChanged;
        public void NofityPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }
}
